package com.wtf.dsp.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wtf.dsp.admin.entity.WtfDspMapper;
import com.wtf.dsp.admin.enums.BizType;
import com.wtf.dsp.admin.enums.CloneType;
import com.wtf.dsp.admin.enums.DataCloneScope;
import com.wtf.dsp.admin.core.model.DataSourceInfo;
import com.wtf.dsp.admin.entity.WtfDspDatasource;
import com.wtf.dsp.admin.entity.WtfDspNamespace;
import com.wtf.dsp.admin.enums.CommonErrorEnum;
import com.wtf.dsp.admin.exception.WtfDspException;
import com.wtf.dsp.admin.core.executor.WtfDynamicDataSourceProviderExecutor;
import com.wtf.dsp.admin.core.executor.WtfDynamicDataSourceMybatisConfigExecutor;
import com.wtf.dsp.admin.mapper.WtfDspDatasourceMapper;
import com.wtf.dsp.admin.mapper.WtfDspMapperMapper;
import com.wtf.dsp.admin.mapper.WtfDspNamespaceMapper;
import com.wtf.dsp.admin.mapper.WtfDspSqlMapper;
import com.wtf.dsp.admin.model.dto.*;
import com.wtf.dsp.admin.model.vo.DsCloneVO;
import com.wtf.dsp.admin.model.vo.DsVO;
import com.wtf.dsp.admin.model.vo.SqlVO;
import com.wtf.dsp.admin.service.DataSourceService;
import com.wtf.dsp.admin.service.MapperService;
import com.wtf.dsp.admin.service.SqlService;
import com.wtf.dsp.core.constant.NsConstant;
import com.wtf.dsp.core.enums.SqlType;
import com.wtf.dsp.core.util.PageUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * date: 2022/6/18 10:59
 * @author linhuanyou
 * @email 496558736@qq.com
 * @version 1.0
 */
@Slf4j
@Service
public class DataSourceServiceImpl implements DataSourceService {

    @Autowired
    private WtfDynamicDataSourceProviderExecutor wtfDynamicDataSourceProviderExecutor;

    @Resource
    private WtfDspDatasourceMapper wtfDspDatasourceMapper;

    @Resource
    private WtfDspNamespaceMapper wtfDspNamespaceMapper;

    @Resource
    private WtfDspMapperMapper wtfDspMapperMapper;

    @Resource
    private WtfDspSqlMapper wtfDspSqlMapper;

    @Resource
    private SqlService sqlService;

    @Resource
    private MapperService mapperService;
    
    @Lazy
    @Autowired
    private WtfDynamicDataSourceMybatisConfigExecutor wtfDynamicDataSourceMybatisConfigExecutor;

    @Override
    public PageUtils page(DsPageDTO dsPageDTO) {
        if(StringUtils.isBlank(dsPageDTO.getNs())){
            dsPageDTO.setNs(NsConstant.DEFAULT_NS);
        }
        Page<?> page = PageHelper.startPage(dsPageDTO.getPage(), dsPageDTO.getLimit());
        DsListDTO dsListDTO = new DsListDTO();
        dsListDTO.setNs(dsPageDTO.getNs());
        dsListDTO.setDs(dsPageDTO.getDs());
        List<DsVO> dataSources = list(dsListDTO);
        return new PageUtils(dataSources, (int) page.getTotal(), dsPageDTO.getLimit(),dsPageDTO.getPage());
    }

    @Override
    public List<DsVO> list(DsListDTO dsListDTO) {
        if(StringUtils.isBlank(dsListDTO.getNs())){
            dsListDTO.setNs(NsConstant.DEFAULT_NS);
        }
        LambdaQueryWrapper<WtfDspDatasource> wtfDataSourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDataSourceLambdaQueryWrapper.eq(WtfDspDatasource::getNs,dsListDTO.getNs());
        if(StringUtils.isNotBlank(dsListDTO.getDs())){
            wtfDataSourceLambdaQueryWrapper.like(WtfDspDatasource::getDs,dsListDTO.getDs());
        }
        List<DsVO> dataSources = wtfDspDatasourceMapper.selectList(wtfDataSourceLambdaQueryWrapper).stream().map(e->{
            DsVO dsVO = new DsVO();
            BeanUtils.copyProperties(e,dsVO);
            dsVO.setPassword("******");
            dsVO.setDbType(DbType.getDbType(e.getDbType()));
            return dsVO;
        }).collect(Collectors.toList());
        return dataSources;
    }

    @Override
    public DsVO info(DsListDTO dsListDTO) {
        if(StringUtils.isBlank(dsListDTO.getNs())){
            dsListDTO.setNs(NsConstant.DEFAULT_NS);
        }
        LambdaQueryWrapper<WtfDspDatasource> wtfDataSourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDataSourceLambdaQueryWrapper.eq(WtfDspDatasource::getNs,dsListDTO.getNs());
        if(StringUtils.isBlank(dsListDTO.getDs())){
            return null;
        }
        wtfDataSourceLambdaQueryWrapper.eq(WtfDspDatasource::getDs,dsListDTO.getDs());
        WtfDspDatasource dataSource = wtfDspDatasourceMapper.getDataSource(dsListDTO.getNs(), dsListDTO.getDs());
        DsVO dsVO = new DsVO();
        BeanUtils.copyProperties(dataSource,dsVO);
        dsVO.setDbType(DbType.getDbType(dataSource.getDbType()));
        return dsVO;
    }

    @Override
    public List<DsVO> list(String ns, String ds) {
        DsListDTO dsListDTO = new DsListDTO();
        dsListDTO.setNs(ns);
        dsListDTO.setDs(ds);
        List<DsVO> dataSources = list(dsListDTO);
        return dataSources;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public int add(DsAddDTO dsDbDTO) {
        //数据库操作
        LambdaQueryWrapper<WtfDspDatasource> wtfDspDatasourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDspDatasourceLambdaQueryWrapper.eq(WtfDspDatasource::getNs,dsDbDTO.getNs());
        wtfDspDatasourceLambdaQueryWrapper.eq(WtfDspDatasource::getDs,dsDbDTO.getDs());
        if(wtfDspDatasourceMapper.selectCount(wtfDspDatasourceLambdaQueryWrapper) > 0){
            throw new WtfDspException(CommonErrorEnum.DATA_SOURCE_EXIST);
        }
        WtfDspDatasource wtfDspDatasource = new WtfDspDatasource();
        wtfDspDatasource.setNs(dsDbDTO.getNs());
        wtfDspDatasource.setDs(dsDbDTO.getDs());
        wtfDspDatasource.setDbName(dsDbDTO.getDbName());
        wtfDspDatasource.setDbType(dsDbDTO.getDbType().getDb());
        wtfDspDatasource.setHost(dsDbDTO.getHost());
        wtfDspDatasource.setPort(dsDbDTO.getPort());
        wtfDspDatasource.setUsername(dsDbDTO.getUsername());
        wtfDspDatasource.setPassword(dsDbDTO.getPassword());
        wtfDspDatasource.setConnectionTestQuery(dsDbDTO.getConnectionTestQuery());
        wtfDspDatasource.setConnectionTimeout(dsDbDTO.getConnectionTimeout());
        wtfDspDatasource.setValidationTimeout(dsDbDTO.getValidationTimeout());
        wtfDspDatasource.setIdleTimeout(dsDbDTO.getIdleTimeout());
        wtfDspDatasource.setLeakDetectionThreshold(dsDbDTO.getLeakDetectionThreshold());
        wtfDspDatasource.setMaxLifetime(dsDbDTO.getMaxLifetime());
        wtfDspDatasource.setMinIdle(dsDbDTO.getMinIdle());
        wtfDspDatasource.setMaxPoolSize(dsDbDTO.getMaxPoolSize());
        int insert = wtfDspDatasourceMapper.insert(wtfDspDatasource);
        //增加命名空间的数据源的mybatis配置
        if(insert > 0){
            DataSourceInfo dataSourceInfo = new DataSourceInfo();
            BeanUtils.copyProperties(dsDbDTO,dataSourceInfo);
            wtfDynamicDataSourceMybatisConfigExecutor.initDsMybatisConfig(dataSourceInfo);
        }
        return insert;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int update(DsUpdateDTO dsUpdateDTO) {
        LambdaQueryWrapper<WtfDspDatasource> wtfDspDatasourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDspDatasourceLambdaQueryWrapper.eq(WtfDspDatasource::getNs,dsUpdateDTO.getNs());
        wtfDspDatasourceLambdaQueryWrapper.eq(WtfDspDatasource::getDs,dsUpdateDTO.getDs());
        WtfDspDatasource oldDs = wtfDspDatasourceMapper.selectOne(wtfDspDatasourceLambdaQueryWrapper);
        if( oldDs == null){
            throw new WtfDspException(CommonErrorEnum.DATA_SOURCE_NOT_EXIST);
        }
        Integer id = oldDs.getId();
        WtfDspDatasource wtfDspDatasource = new WtfDspDatasource();
        wtfDspDatasource.setId(id);
        if(StringUtils.isNotBlank(dsUpdateDTO.getDbName())){
            wtfDspDatasource.setDbName(dsUpdateDTO.getDbName());
        }
        if(StringUtils.isNotBlank(dsUpdateDTO.getHost())){
            wtfDspDatasource.setHost(dsUpdateDTO.getHost());
        }
        if(dsUpdateDTO.getPort() != null){
            wtfDspDatasource.setPort(dsUpdateDTO.getPort());
        }
        if(StringUtils.isNotBlank(dsUpdateDTO.getUsername())){
            wtfDspDatasource.setUsername(dsUpdateDTO.getUsername());
        }
        if(StringUtils.isNotBlank(dsUpdateDTO.getPassword())){
            wtfDspDatasource.setPassword(dsUpdateDTO.getPassword());
        }
        if(StringUtils.isNotBlank(dsUpdateDTO.getConnectionTestQuery())){
            wtfDspDatasource.setConnectionTestQuery(dsUpdateDTO.getConnectionTestQuery());
        }
        if(dsUpdateDTO.getConnectionTimeout() != null){
            wtfDspDatasource.setConnectionTimeout(dsUpdateDTO.getConnectionTimeout());
        }
        if(dsUpdateDTO.getValidationTimeout() != null){
            wtfDspDatasource.setValidationTimeout(dsUpdateDTO.getValidationTimeout());
        }
        if(dsUpdateDTO.getIdleTimeout() != null){
            wtfDspDatasource.setIdleTimeout(dsUpdateDTO.getIdleTimeout());
        }
        if(dsUpdateDTO.getLeakDetectionThreshold() != null){
            wtfDspDatasource.setLeakDetectionThreshold(dsUpdateDTO.getLeakDetectionThreshold());
        }
        if(dsUpdateDTO.getMaxLifetime() != null){
            wtfDspDatasource.setMaxLifetime(dsUpdateDTO.getMaxLifetime());
        }
        if(dsUpdateDTO.getMinIdle() !=  null){
            wtfDspDatasource.setMinIdle(dsUpdateDTO.getMinIdle());
        }
        if(dsUpdateDTO.getMaxPoolSize() !=  null){
            wtfDspDatasource.setMaxPoolSize(dsUpdateDTO.getMaxPoolSize());
        }
        int update = wtfDspDatasourceMapper.updateById(wtfDspDatasource);
        if(update > 0){
            wtfDynamicDataSourceMybatisConfigExecutor.refreshDataSource(dsUpdateDTO.getNs(),dsUpdateDTO.getDs());
        }
        return update;
    }

    @Override
    public int remove(DsDelDTO dsDelDTO) {
        //删除数据源
        LambdaQueryWrapper<WtfDspMapper> wtfDspMapperLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDspMapperLambdaQueryWrapper.eq(WtfDspMapper::getNs,dsDelDTO.getNs());
        wtfDspMapperLambdaQueryWrapper.in(WtfDspMapper::getDs,dsDelDTO.getDss());
        Integer dsMapperCounts = wtfDspMapperMapper.selectCount(wtfDspMapperLambdaQueryWrapper);
        if(dsMapperCounts >0){
            throw new WtfDspException(CommonErrorEnum.DS_MAPPER_ERROR);
        }
        LambdaQueryWrapper<WtfDspDatasource> wtfDspDatasourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDspDatasourceLambdaQueryWrapper.eq(WtfDspDatasource::getNs,dsDelDTO.getNs());
        wtfDspDatasourceLambdaQueryWrapper.in(WtfDspDatasource::getDs,dsDelDTO.getDss());
        int delete = wtfDspDatasourceMapper.delete(wtfDspDatasourceLambdaQueryWrapper);
        if(delete > 0){
            dsDelDTO.getDss().forEach(new Consumer<String>() {
                @Override
                public void accept(String ds) {
                    wtfDynamicDataSourceMybatisConfigExecutor.clearDynamicDataSource(dsDelDTO.getNs(),ds);
                }
            });
        }
        return delete;
    }

    @Override
    public Boolean testConnect(DsAddDTO dsDbDTO) throws Exception {
        DataSourceInfo dataSourceInfo = new DataSourceInfo();
        BeanUtils.copyProperties(dsDbDTO,dataSourceInfo);
        return wtfDynamicDataSourceMybatisConfigExecutor.testConnect(dataSourceInfo);
    }

    @Override
    public DsCloneVO clone(DsCloneDTO dsCloneDTO) {
        //克隆数据源信息
        List<SourceInfoDTO> cloneInfos = dsCloneDTO.getSourceInfos();
        BizType bizType = dsCloneDTO.getBizType();
        boolean present = cloneInfos.stream().filter(e -> {
            return bizType == BizType.DS ?  StringUtils.isBlank(e.getDs())  : bizType == BizType.MNS ? StringUtils.isBlank(e.getDs()) || StringUtils.isBlank(e.getMns()) : StringUtils.isBlank(e.getDs()) || StringUtils.isBlank(e.getMns()) || StringUtils.isBlank(e.getSqlId());
        }).findFirst().isPresent();
        Assert.isFalse(present,"克隆数据源信息参数错误");

        //目标命名空间判断
        LambdaQueryWrapper<WtfDspNamespace> targetNsWrapper = new LambdaQueryWrapper<>();
        targetNsWrapper.eq(WtfDspNamespace::getNs,dsCloneDTO.getTargetNs());
        if(wtfDspNamespaceMapper.selectCount(targetNsWrapper) == 0){
            throw new WtfDspException(CommonErrorEnum.TARGET_NAMESPACE_NOT_EXIST);
        }

        //来源命名空间判断
        LambdaQueryWrapper<WtfDspNamespace> sourceNsWrapper = new LambdaQueryWrapper<>();
        sourceNsWrapper.eq(WtfDspNamespace::getNs,dsCloneDTO.getSourceNs());
        if(wtfDspNamespaceMapper.selectCount(sourceNsWrapper) == 0){
            throw new WtfDspException(CommonErrorEnum.NAMESPACE_NOT_EXIST);
        }
        //目标命名空间
        String targetNs = dsCloneDTO.getTargetNs();
        String sourceNs = dsCloneDTO.getSourceNs();

        //查询源命名空间的所有ds、mns、sql
        List<SqlVO> sourceSqls = wtfDspMapperMapper.getSqls(sourceNs, null, null, null);
        Map<String, Integer> sourceDss = sourceSqls.stream().map(SqlVO::getDs).distinct().collect(Collectors.toMap(k -> k, v -> 1));
        Map<String, Integer> sourceMnss = sourceSqls.stream().filter(e -> {
            return StringUtils.isNotBlank(e.getMns());
        }).map(e->{return NsConstant.mapperNamespace(e.getDs(), e.getMns());}).distinct().collect(Collectors.toMap(k -> k, v -> 1));
        Map<String, Integer> sourceSqlss = sourceSqls.stream().filter(e -> {
            return StringUtils.isNotBlank(e.getSqlId());
        }).map(e->{return NsConstant.mapperNamespace(e.getDs(), e.getMns(), e.getSqlId());}).distinct().collect(Collectors.toMap(k -> k, v -> 1));

        if (cloneInfos.stream().filter(e -> {
            return !sourceDss.containsKey(e.getDs());
        }).findFirst().isPresent()) {
            throw new WtfDspException(CommonErrorEnum.DATA_SOURCE_NOT_EXIST);
        }

        if(bizType == BizType.MNS){
            if (cloneInfos.stream().filter(e -> {
                return !sourceMnss.containsKey(NsConstant.mapperNamespace(e.getDs(),e.getMns()));
            }).findFirst().isPresent()) {
                throw new WtfDspException(CommonErrorEnum.MAPPER_NOT_EXIST);
            }
        }

        if(bizType == BizType.SQL){
            if (cloneInfos.stream().filter(e -> {
                return !sourceSqlss.containsKey(NsConstant.mapperNamespace(e.getDs(),e.getMns(),e.getSqlId()));
            }).findFirst().isPresent()) {
                throw new WtfDspException(CommonErrorEnum.MAPPER_SQL_NOT_EXIST);
            }
        }

        //查询目标命名空间的所有ds、mns、sql
        List<SqlVO> targetSqls = wtfDspMapperMapper.getSqls(targetNs, null, null, null);
        Map<String, Integer> targetDss = targetSqls.stream().map(SqlVO::getDs).distinct().collect(Collectors.toMap(k -> k, v -> 1));
        Map<String, Integer> targetMnss = targetSqls.stream().filter(e -> {
            return StringUtils.isNotBlank(e.getMns());
        }).map(e->{return NsConstant.mapperNamespace(e.getDs(), e.getMns());}).distinct().collect(Collectors.toMap(k -> k, v -> 1));
        Map<String, Integer> targetSqlss = targetSqls.stream().filter(e -> {
            return StringUtils.isNotBlank(e.getSqlId());
        }).map(e->{return NsConstant.mapperNamespace(e.getDs(), e.getMns(), e.getSqlId());}).distinct().collect(Collectors.toMap(k -> k, v -> 1));


        Map<String, Integer> cloneDss = cloneInfos.stream().map(SourceInfoDTO::getDs).distinct().collect(Collectors.toMap(k -> k, v -> 1));
        Map<String, Integer> cloneMnss = cloneInfos.stream().filter(e -> {
            return StringUtils.isNotBlank(e.getMns());
        }).map(e->{return NsConstant.mapperNamespace(e.getDs(), e.getMns());}).distinct().collect(Collectors.toMap(k -> k, v -> 1));
        Map<String, Integer> cloneSqlss = cloneInfos.stream().filter(e -> {
            return StringUtils.isNotBlank(e.getSqlId());
        }).map(e->{return NsConstant.mapperNamespace(e.getDs(), e.getMns(), e.getSqlId());}).distinct().collect(Collectors.toMap(k -> k, v -> 1));

        List<String> dsAdd = new ArrayList<>();
        List<String> dsOnlyAdd = new ArrayList<>();
        List<String> mnsAdd = new ArrayList<>();
        List<String> mnsOnlyAdd = new ArrayList<>();
        List<String> sqlAdd = new ArrayList<>();

        List<String> dsDel = new ArrayList<>();
        List<String> mnsDel = new ArrayList<>();
        List<String> sqlDel = new ArrayList<>();
        //克隆类型
        CloneType cloneType = dsCloneDTO.getCloneType();
        //克隆数据范围
        DataCloneScope dataCloneScope = dsCloneDTO.getDataCloneScope();

        if(dsCloneDTO.getBizType() == BizType.DS){
            if(cloneType == CloneType.TERMINATE_IMPORT){
                //终止导入
                //判断克隆的ds是否存在目标命名空间
                dsAdd.addAll(cloneDss.keySet().stream().collect(Collectors.toList()));
                if(dsAdd.stream().filter(e->{return targetDss.containsKey(e);}).findFirst().isPresent()){
                    throw new WtfDspException(CommonErrorEnum.TARGET_DATA_SOURCE_EXIST);
                }
            } else if(cloneType == CloneType.SKIP){
                //跳过
                //判断不存在目标命名空间的数据源cDss
                dsAdd.addAll(cloneDss.keySet().stream().filter(e -> {
                    return !targetDss.containsKey(e);
                }).distinct().collect(Collectors.toList()));
            } else {
                //覆盖
                dsAdd.addAll(cloneDss.keySet().stream().collect(Collectors.toList()));
                dsDel.addAll(dsAdd.stream().filter(e -> {
                    return targetDss.containsKey(e);
                }).distinct().collect(Collectors.toList()));
            }
        } else if(dsCloneDTO.getBizType() == BizType.MNS){
            if(cloneType == CloneType.TERMINATE_IMPORT){
                //终止导入
                mnsAdd.addAll(cloneMnss.keySet().stream().collect(Collectors.toList()));
                if(mnsAdd.stream().filter(e->{return targetMnss.containsKey(e);}).findFirst().isPresent()){
                    throw new WtfDspException(CommonErrorEnum.TARGET_MAPPER_EXIST);
                }
            } else if(cloneType == CloneType.SKIP){
                //跳过
                mnsAdd.addAll(cloneMnss.keySet().stream().filter(e -> {
                    return !targetMnss.containsKey(e);
                }).distinct().collect(Collectors.toList()));
            } else {
                //覆盖
                mnsAdd.addAll(cloneMnss.keySet().stream().collect(Collectors.toList()));
                mnsDel.addAll(mnsAdd.stream().filter(e -> {
                    return targetMnss.containsKey(e);
                }).distinct().collect(Collectors.toList()));
            }
            mnsAdd.forEach(new Consumer<String>() {
                @Override
                public void accept(String dsMns) {
                    String[] split = dsMns.split(NsConstant._SPLIT);
                    if(!targetDss.containsKey(split[0])){
                        dsOnlyAdd.add(split[0]);
                    }
                }
            });
        } else {
            if(cloneType == CloneType.TERMINATE_IMPORT){
                //终止导入
                sqlAdd.addAll(cloneSqlss.keySet().stream().collect(Collectors.toList()));
                if(sqlAdd.stream().filter(e->{return targetSqlss.containsKey(e);}).findFirst().isPresent()){
                    throw new WtfDspException(CommonErrorEnum.TARGET_MAPPER_EXIST);
                }
            } else if(cloneType == CloneType.SKIP){
                //跳过
                sqlAdd.addAll(cloneSqlss.keySet().stream().filter(e -> {
                    return !targetSqlss.containsKey(e);
                }).distinct().collect(Collectors.toList()));
            } else {
                //覆盖
                sqlAdd.addAll(cloneSqlss.keySet().stream().collect(Collectors.toList()));
                sqlDel.addAll(sqlAdd.stream().filter(e -> {
                    return targetSqlss.containsKey(e);
                }).distinct().collect(Collectors.toList()));
            }
            dsOnlyAdd.addAll(sqlAdd.stream().map(e->{return e.split(NsConstant._SPLIT)[0];}).distinct().filter(e->{return !targetDss.containsKey(e);}).distinct().collect(Collectors.toList()));
            mnsOnlyAdd.addAll(sqlAdd.stream().map(e->{return NsConstant.mapperNamespace(e.split(NsConstant._SPLIT)[0],e.split(NsConstant._SPLIT)[1]);}).distinct().filter(e->{return !targetMnss.containsKey(e);}).distinct().collect(Collectors.toList()));
        }
        if(dataCloneScope == DataCloneScope.ALL){
            List<String> delCMnss = targetMnss.keySet().stream().filter(e -> {
                return dsDel.stream().filter(e1 -> {
                    return e.startsWith(e1);
                }).findFirst().isPresent();
            }).distinct().collect(Collectors.toList());
            mnsDel.addAll(delCMnss);
            List<String> delCSqls = targetSqlss.keySet().stream().filter(e -> {
                return mnsDel.stream().filter(e1 -> {
                    return e.startsWith(e1);
                }).findFirst().isPresent();
            }).collect(Collectors.toList());
            sqlDel.addAll(delCSqls);

            List<String> cMnss = sourceMnss.keySet().stream().filter(e -> {
                return dsAdd.stream().filter(e1 -> {
                    return e.startsWith(e1);
                }).findFirst().isPresent();
            }).collect(Collectors.toList());
            mnsAdd.addAll(cMnss);
            List<String> cSqls = sourceSqlss.keySet().stream().filter(e -> {
                return mnsAdd.stream().filter(e1 -> {
                    return e.startsWith(e1);
                }).findFirst().isPresent();
            }).collect(Collectors.toList());
            sqlAdd.addAll(cSqls);
        }
        DsCloneVO dsCloneVO = new DsCloneVO();
        if(CollUtil.isNotEmpty(sqlDel)){
            sqlDel.stream().collect(Collectors.groupingBy(k-> NsConstant.mapperNamespace(k.split(NsConstant._SPLIT)[0],k.split(NsConstant._SPLIT)[1]))).forEach(new BiConsumer<String, List<String>>() {
                @Override
                public void accept(String dsMns, List<String> sqls) {
                    SqlDelDTO mnsSqlDelDTO = new SqlDelDTO();
                    mnsSqlDelDTO.setNs(targetNs);
                    String[] dsMnsSplit = dsMns.split(NsConstant._SPLIT);
                    mnsSqlDelDTO.setDs(dsMnsSplit[0]);
                    mnsSqlDelDTO.setMns(dsMnsSplit[1]);
                    mnsSqlDelDTO.setSqlIds(sqls.stream().map(e->{return e.split(NsConstant._SPLIT)[2];}).collect(Collectors.toList()));
                    int remove = sqlService.remove(mnsSqlDelDTO);
                }
            });
            dsCloneVO.setSqlDel(sqlDel);
        }

        if(CollUtil.isNotEmpty(mnsDel)){
            mnsDel.stream().collect(Collectors.groupingBy(k-> k.split(NsConstant._SPLIT)[0])).forEach(new BiConsumer<String, List<String>>() {
                @Override
                public void accept(String ds, List<String> mnss) {
                    MnsDelDTO dsMnsDelDTO = new MnsDelDTO();
                    dsMnsDelDTO.setNs(targetNs);
                    dsMnsDelDTO.setDs(ds);
                    dsMnsDelDTO.setMnss(mnss.stream().map(e->{return e.split(NsConstant._SPLIT)[1];}).collect(Collectors.toList()));
                    int remove = mapperService.remove(dsMnsDelDTO);
                }
            });
            dsCloneVO.setMnsDel(mnsDel);
        }

        if(CollUtil.isNotEmpty(dsDel)){
            DsDelDTO dsDelDTO = new DsDelDTO();
            dsDelDTO.setNs(targetNs);
            dsDelDTO.setDss(dsDel);
            int remove = remove(dsDelDTO);
            dsCloneVO.setDsDel(dsDel);
        }
        //新增数据源
        dsAdd.addAll(dsOnlyAdd);
        if(CollUtil.isNotEmpty(dsAdd)){
            dsAdd.forEach(new Consumer<String>() {
                @Override
                public void accept(String ds) {
                    DataSourceInfo dataSource = wtfDynamicDataSourceMybatisConfigExecutor.getDataSource(sourceNs, ds);
                    DsAddDTO dsAddDTO = new DsAddDTO();
                    BeanUtils.copyProperties(dataSource,dsAddDTO);
                    dsAddDTO.setNs(targetNs);
                    int add = add(dsAddDTO);
                }
            });
            dsCloneVO.setDsAdd(dsAdd);
        }

        //新增mapper
        mnsAdd.addAll(mnsOnlyAdd);
        if(CollUtil.isNotEmpty(mnsAdd)){
            mnsAdd.forEach(new Consumer<String>() {
                @Override
                public void accept(String dsMns) {
                    MnsAddDTO dsMnsAddDTO1 = new MnsAddDTO();
                    dsMnsAddDTO1.setNs(targetNs);
                    String[] dsMnsSplit = dsMns.split(NsConstant._SPLIT);
                    dsMnsAddDTO1.setDs(dsMnsSplit[0]);
                    dsMnsAddDTO1.setMns(dsMnsSplit[1]);
                    int add = mapperService.add(dsMnsAddDTO1);
                }
            });
            dsCloneVO.setMnsAdd(mnsAdd);
        }
        //新增SQL
        if(CollUtil.isNotEmpty(sqlAdd)){
            sqlAdd.forEach(new Consumer<String>() {
                @Override
                public void accept(String dsMnsSql) {
                    SqlAddDTO mnsSqlAddDTO = new SqlAddDTO();
                    mnsSqlAddDTO.setNs(targetNs);
                    String[] dsMnsSqlSplit = dsMnsSql.split(NsConstant._SPLIT);
                    mnsSqlAddDTO.setDs(dsMnsSqlSplit[0]);
                    mnsSqlAddDTO.setMns(dsMnsSqlSplit[1]);
                    mnsSqlAddDTO.setSqlId(dsMnsSqlSplit[2]);
                    SqlVO sqlVO = sourceSqls.stream().filter(e -> {
                        return mnsSqlAddDTO.getDs().equals(e.getDs()) && mnsSqlAddDTO.getMns().equals(e.getMns()) && mnsSqlAddDTO.getSqlId().equals(e.getSqlId());
                    }).findFirst().get();
                    mnsSqlAddDTO.setDescription(sqlVO.getDescription());
                    mnsSqlAddDTO.setSqlStatement(sqlVO.getSqlStatement());
                    mnsSqlAddDTO.setSqlType(SqlType.valueOf(sqlVO.getSqlType()));
                    int add = sqlService.add(mnsSqlAddDTO);
                }
            });
            dsCloneVO.setSqlAdd(sqlAdd);
        }
        return dsCloneVO;
    }
}
